package org.example.redis.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author 小杰_cc
 * @version 1.0
 */
@Component
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public class RedisService {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 缓存基本对象, 不带过期时间
     */
    public <T> void setObject(String key, T value){
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 缓存基本对象, 带过期时间
     */
    public <T> void setObject(String key, T value, Long time, TimeUnit unit){
        redisTemplate.opsForValue().set(key, value, time, unit);
    }

    /**
     * 获得缓存的对象
     */
    public <T> T getObject(String key){
        return (T) redisTemplate.opsForValue().get(key);
    }

    /**
     * 删除缓存的对象
     */
    public boolean deleteObject(String key){
        return Boolean.TRUE.equals(redisTemplate.delete(key));
    }

    /**
     * 设置有效期
     */
    public boolean setExpire(String key, Long time, TimeUnit unit){
        return Boolean.TRUE.equals(redisTemplate.expire(key, time, unit));
    }

    /**
     * 使key的值减一
     * @param key
     */
    public void setMinus(String key, Integer step){
        redisTemplate.opsForValue().increment(key, step);
    }

    /**
     * 存入数据到hash
     */
    public <T> void setHash(String key, String hashKey, T data){
        redisTemplate.opsForHash().put(key, hashKey, data);
    }

    /**
     * 存入数据到hash
     */
    public <T> void setHashAll(String key, Map<String, T> data){
        redisTemplate.opsForHash().putAll(key, data);
    }

    /**
     * hash判断某个filed是否存在
     */
    public boolean existHasKey(String key, String hashKey){
        return redisTemplate.opsForHash().hasKey(key, hashKey);
    }

    /**
     * 获取单个hash中key对应的filed的value值
     */
    public <T> T getHashValue(String key, String hasKey){
        return (T) redisTemplate.opsForHash().get(key, hasKey);
    }

    /**
     * 获取hash中对应key的所有filed和value值
     */
    public <HK, HV> Map<HK, HV> getHash(String key){
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 获取hash中对应key的所有value
     * @param key
     * @return
     * @param <HV>
     */
    public <HV> List<HV> getHashValues(String key){
        return redisTemplate.opsForHash().values(key);
    }

    /**
     * 获取hash中对应key的filed集合
     */
    public <HV> List<HV> getFiledValues(String key, List<String> hasKeys){
        return redisTemplate.opsForHash().multiGet(key, hasKeys);
    }

    /**
     * 删除hash中对应key的file
     */
    public void deleteHashValue(String key, Object... hasKey){
        redisTemplate.opsForHash().delete(key, hasKey);
    }

    /**
     * 获取hash中对应key的field的个数
     */
    public Long getHashCount(String key){
        return redisTemplate.opsForHash().size(key);
    }

    /**
     * lua脚本
     */
    public <T> Object execute(RedisScript<T> script, List keys, Object... args){
        return redisTemplate.execute(script, keys, args);
    }

    /**
     * 生成序列号的方法
     */
    public Long createSn(String key){
        return redisTemplate.opsForValue().increment(key);
    }

    /**
     * 保存数据到Set中
     * @param key
     * @param data
     * @param <T>
     */
    public <T> void setSetObject(String key, T data){
        redisTemplate.opsForSet().add(key, data);
    }

    /**
     * set判断某个元素是否在key中
     * @param key
     * @param data
     * @return
     * @param <T>
     */
    public <T> boolean isExistSet(String key, T data){
        return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, data));
    }


    public void deleteSetObject(String key, Object[] data){
        redisTemplate.opsForSet().remove(key, data);
    }

    /**
     * 保存数据到SortedSet
     * @param key
     * @param data
     * @param score 分数，用于排序
     * @param <T>
     */
    public <T> void setSortSetObject(String key, T data, Double score){
        redisTemplate.opsForZSet().add(key, data, score);
    }

    public <T> void setListRight(String key, T data){
        redisTemplate.opsForList().rightPush(key, data);
    }

    public <T> void setListLeft(String key, T data){
        redisTemplate.opsForList().leftPush(key, data);
    }

    public <T> void setListRightAll(String key, List<T> data){
        redisTemplate.opsForList().rightPushAll(key, data);
    }

    public <T> void setListLeftAll(String key, List<T> data){
        redisTemplate.opsForList().leftPushAll(key, data);
    }

    public boolean isKeyExist(String key){
        return Boolean.TRUE.equals(redisTemplate.hasKey(key));
    }

    public Set<String> getKey(String key){
        return redisTemplate.keys(key);
    }
}